package service

import (
	"context"
	"net/http"

	"github.com/mars/internal/admin/core/domain"
	"github.com/mars/pkg/errors"
	"github.com/mars/pkg/loggers"
)

type OrderSrv interface {
	GetOrderList(ctx context.Context, params domain.OrderQueryParams) ([]domain.Order, int64, error)
	GetOrder(ctx context.Context, orderID string) (*domain.Order, error)
	UpdateOrderStatus(ctx context.Context, orderID string, status domain.OrderStatus) error
	ProcessRefund(ctx context.Context, orderID string, reason string, amount *int) error
	GetOrderStats(ctx context.Context) (*domain.OrderStats, error)
	SearchOrders(ctx context.Context, keyword string) ([]domain.Order, error)
	GetOrdersByStatus(ctx context.Context, status domain.OrderStatus) ([]domain.Order, error)
	GetOrdersByPaymentMethod(ctx context.Context, paymentMethod domain.PaymentMethod) ([]domain.Order, error)
	GetVipOrders(ctx context.Context) ([]domain.Order, error)
	ExportOrders(ctx context.Context, params domain.OrderQueryParams) ([]domain.Order, error)
}

type orderService struct {
	orderDomain domain.OrderGateway
}

var _ OrderSrv = (*orderService)(nil)

func newOrderService(fc domain.Factory) *orderService {
	return &orderService{
		orderDomain: fc.OrderGateway(),
	}
}

// GetOrderList implements OrderSrv.
func (o *orderService) GetOrderList(ctx context.Context, params domain.OrderQueryParams) ([]domain.Order, int64, error) {
	orders, total, err := o.orderDomain.GetOrderList(ctx, params)
	if err != nil {
		loggers.Error(ctx, "get order list failed", err)
		return nil, 0, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get order list failed")
	}
	return orders, total, nil
}

// GetOrder implements OrderSrv.
func (o *orderService) GetOrder(ctx context.Context, orderID string) (*domain.Order, error) {
	order, err := o.orderDomain.GetOrder(ctx, orderID)
	if err != nil {
		loggers.Error(ctx, "get order failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get order failed")
	}
	return order, nil
}

// UpdateOrderStatus implements OrderSrv.
func (o *orderService) UpdateOrderStatus(ctx context.Context, orderID string, status domain.OrderStatus) error {
	// 检查订单是否存在
	order, err := o.orderDomain.GetOrder(ctx, orderID)
	if err != nil {
		loggers.Error(ctx, "order not found", err)
		return errors.NewWithStackWithoutCode(http.StatusNotFound, "order not found")
	}

	// 验证状态转换逻辑
	if err := o.validateStatusTransition(order.Status, status); err != nil {
		return err
	}

	err = o.orderDomain.UpdateOrderStatus(ctx, orderID, status)
	if err != nil {
		loggers.Error(ctx, "update order status failed", err)
		return errors.NewWithStackWithoutCode(http.StatusInternalServerError, "update order status failed")
	}
	return nil
}

// ProcessRefund implements OrderSrv.
func (o *orderService) ProcessRefund(ctx context.Context, orderID string, reason string, amount *int) error {
	// 检查订单是否存在
	order, err := o.orderDomain.GetOrder(ctx, orderID)
	if err != nil {
		loggers.Error(ctx, "order not found", err)
		return errors.NewWithStackWithoutCode(http.StatusNotFound, "order not found")
	}

	// 验证订单状态是否可以退款
	if !o.canRefund(order.Status) {
		return errors.NewWithStackWithoutCode(http.StatusBadRequest, "order status does not allow refund")
	}

	// 验证退款金额
	if amount != nil && *amount > order.TotalAmount {
		return errors.NewWithStackWithoutCode(http.StatusBadRequest, "refund amount cannot exceed total amount")
	}

	err = o.orderDomain.ProcessRefund(ctx, orderID, reason, amount)
	if err != nil {
		loggers.Error(ctx, "process refund failed", err)
		return errors.NewWithStackWithoutCode(http.StatusInternalServerError, "process refund failed")
	}
	return nil
}

// GetOrderStats implements OrderSrv.
func (o *orderService) GetOrderStats(ctx context.Context) (*domain.OrderStats, error) {
	stats, err := o.orderDomain.GetOrderStats(ctx)
	if err != nil {
		loggers.Error(ctx, "get order stats failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get order stats failed")
	}
	return stats, nil
}

// SearchOrders implements OrderSrv.
func (o *orderService) SearchOrders(ctx context.Context, keyword string) ([]domain.Order, error) {
	if keyword == "" {
		return []domain.Order{}, nil
	}

	orders, err := o.orderDomain.SearchOrders(ctx, keyword)
	if err != nil {
		loggers.Error(ctx, "search orders failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "search orders failed")
	}
	return orders, nil
}

// GetOrdersByStatus implements OrderSrv.
func (o *orderService) GetOrdersByStatus(ctx context.Context, status domain.OrderStatus) ([]domain.Order, error) {
	orders, err := o.orderDomain.GetOrdersByStatus(ctx, status)
	if err != nil {
		loggers.Error(ctx, "get orders by status failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get orders by status failed")
	}
	return orders, nil
}

// GetOrdersByPaymentMethod implements OrderSrv.
func (o *orderService) GetOrdersByPaymentMethod(ctx context.Context, paymentMethod domain.PaymentMethod) ([]domain.Order, error) {
	orders, err := o.orderDomain.GetOrdersByPaymentMethod(ctx, paymentMethod)
	if err != nil {
		loggers.Error(ctx, "get orders by payment method failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get orders by payment method failed")
	}
	return orders, nil
}

// GetVipOrders implements OrderSrv.
func (o *orderService) GetVipOrders(ctx context.Context) ([]domain.Order, error) {
	orders, err := o.orderDomain.GetVipOrders(ctx)
	if err != nil {
		loggers.Error(ctx, "get vip orders failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "get vip orders failed")
	}
	return orders, nil
}

// ExportOrders implements OrderSrv.
func (o *orderService) ExportOrders(ctx context.Context, params domain.OrderQueryParams) ([]domain.Order, error) {
	// 导出时移除分页限制
	params.Page = 1
	params.PageSize = 10000 // 设置一个较大的默认值

	orders, err := o.orderDomain.ExportOrders(ctx, params)
	if err != nil {
		loggers.Error(ctx, "export orders failed", err)
		return nil, errors.NewWithStackWithoutCode(http.StatusInternalServerError, "export orders failed")
	}
	return orders, nil
}

// validateStatusTransition 验证状态转换逻辑
func (o *orderService) validateStatusTransition(currentStatus, newStatus domain.OrderStatus) error {
	// 定义允许的状态转换规则
	allowedTransitions := map[domain.OrderStatus][]domain.OrderStatus{
		domain.OrderStatusPaid: {
			domain.OrderStatusShipped,   // 已支付 -> 已发货
			domain.OrderStatusCompleted, // 已支付 -> 已完成（虚拟商品）
			domain.OrderStatusRefunding, // 已支付 -> 退款中
		},
		domain.OrderStatusShipped: {
			domain.OrderStatusDelivered, // 已发货 -> 已收货
			domain.OrderStatusRefunding, // 已发货 -> 退款中
		},
		domain.OrderStatusDelivered: {
			domain.OrderStatusCompleted, // 已收货 -> 已完成
			domain.OrderStatusRefunding, // 已收货 -> 退款中
		},
		domain.OrderStatusRefunding: {
			domain.OrderStatusRefunded, // 退款中 -> 已退款
		},
	}

	if allowedTransitions[currentStatus] == nil {
		return errors.NewWithStackWithoutCode(http.StatusBadRequest, "current status does not allow any transitions")
	}

	for _, allowedStatus := range allowedTransitions[currentStatus] {
		if newStatus == allowedStatus {
			return nil
		}
	}

	return errors.NewWithStackWithoutCode(http.StatusBadRequest, "invalid status transition")
}

// canRefund 检查订单是否可以退款
func (o *orderService) canRefund(status domain.OrderStatus) bool {
	refundableStatuses := []domain.OrderStatus{
		domain.OrderStatusPaid,
		domain.OrderStatusShipped,
		domain.OrderStatusDelivered,
	}

	for _, refundableStatus := range refundableStatuses {
		if status == refundableStatus {
			return true
		}
	}

	return false
}
